package automatica.upgrade;

import java.io.File;
import java.io.IOException;
import java.util.Vector;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import prefuse.data.Table;
import ui.Utility;

public class InfoTable extends Table{
	
	public InfoTable(String path){
		try {
			String content = Utility.readFile(path);
			int d = path.lastIndexOf("/")==-1?path.lastIndexOf("\\")+1:path.lastIndexOf("/")+1;
			if(d!=-1&&d!=0){
				name = path.substring(d, path.lastIndexOf("."));
			}
			
			
			objectTable = new Table();
			constraintTable = new Table();
			
			//generate a table to store the information of the content
			//object table with 2 attributes at most
			objectTable.addColumn("role", int.class);
			objectTable.addColumn("reference", String.class);
			objectTable.addColumn("vocabulary", String.class);
			objectTable.addColumn("attribute1", String.class);
			objectTable.addColumn("attribute2", String.class);
			objectTable.addColumn("attribute3", String.class);
			objectTable.addColumn("geobject", String.class);
			objectTable.addColumn("objectCount", int.class);
			objectTable.addColumn("pointCount", int.class);
			//constraint table with 3 attributes at most
			/*
			 * role = 2 :: advanced point
			 * role = 1 :: point
			 * role = 0 :: line or circle
			 * role = -1 :: redundant object
			 */
			constraintTable.addColumn("role", int.class);
			constraintTable.addColumn("reference", String.class);
			constraintTable.addColumn("vocabulary", String.class);
			constraintTable.addColumn("attribute1", String.class);
			constraintTable.addColumn("attribute2", String.class);
			constraintTable.addColumn("attribute3", String.class);
			constraintTable.addColumn("geobject", String.class);
			Vector<String> list = Utility.getItemsBySeparator(content, "\n");
			for(int i = 0; i < list.size(); i++){
				String currentItem = list.get(i);
				if(!currentItem.startsWith("!")){
					int s = currentItem.indexOf(":=");
					//A:=...
					if(s!=-1){
						objectTable.addRow();
						int currentIndex = objectTable.getRowCount()-1;
						objectTable.setString(currentIndex, "reference", currentItem.substring(0,s));
						String str = currentItem.substring(s+2,currentItem.length());
						//if there is no attributes 
						if(str.trim().startsWith("(")){
							objectTable.setString(currentIndex, "vocabulary", "point");
							objectTable.setInt(currentIndex, "role", 1);
							Vector<String> items = Utility.generateTermSet("point"+str);
							objectTable.setString(currentIndex, "attribute1", items.get(1));
							objectTable.setString(currentIndex, "attribute2", items.get(2));
						}else
						if(str.trim().startsWith("point(")){
							objectTable.setString(currentIndex, "vocabulary", "point");
							objectTable.setInt(currentIndex, "role", 1);
							//objectTable.setString(currentIndex, "geobject", str);
						}else{
							Vector<String> items = Utility.generateTermSet(str);
							objectTable.setString(currentIndex, "vocabulary", items.get(0));
							//deal with midpoint(segment(A,B))
							if(items.size()==2&&items.get(1).indexOf("(")!=0){
								items = Utility.generateTermSet(items.get(1));
							}
							for(int k = 1; k < items.size(); k++){
								objectTable.setString(currentIndex, "attribute"+k, items.get(k));
							}
							//set the role for lines and circles with 0
							if(str.trim().startsWith("segment(")||str.trim().startsWith("halfline(")||str.trim().startsWith("line(")||str.trim().startsWith("circle(")){
								objectTable.setInt(currentIndex, "role", 0);
							}else{
								objectTable.setInt(currentIndex,"role",2);
							}
						}
					}else{
						constraintTable.addRow();
						int currentIndex = constraintTable.getRowCount()-1;
						System.out.println(currentItem);
						Vector<String> items = Utility.generateTermSet(currentItem);
						if(items.size()==3){
							constraintTable.setString(currentIndex, "vocabulary", items.get(0));
							constraintTable.setString(currentIndex, "attribute1", items.get(1));
							constraintTable.setString(currentIndex, "attribute2", items.get(2));
							constraintTable.setInt(currentIndex, "role", 1);
						}else{
							JOptionPane.showMessageDialog(null,"The command has more than 2 attributes.",currentItem,JOptionPane.ERROR_MESSAGE);
						}
					}
				}
			}
			
			//initialize the geobject for objectTable
			for(int i = 0; i < objectTable.getRowCount(); i++){
				if(objectTable.getString(i, "geobject")==null){
					objectTable.setString(i,"geobject",getGeobject4ObjectTable(i));
				}
			}
			
			//initialize the count of objects
			//initialCount(objectTable);
			
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	private void updateGeobject4ObjectTable(){
		//initialize the geobject for objectTable
		for(int i = 0; i < objectTable.getRowCount(); i++){
			objectTable.setString(i,"geobject",null);
		}
		for(int i = 0; i < objectTable.getRowCount(); i++){
			if(objectTable.getString(i, "geobject")==null){
				objectTable.setString(i,"geobject",getGeobject4ObjectTable(i));
			}
		}
	}
	
	void updateGeobject4ConstraintTable(){
		//initialize the geobject for constraintTable
		Vector<String> constraints = new Vector<String>(1,1);
		
		//replace the attribute with its construction
//		for(int t = 0; t < constraintTable.getRowCount(); t++){
//			String[] attr = {constraintTable.getString(t, "attribute1"),constraintTable.getString(t, "attribute2"),
//					constraintTable.getString(t, "attribute3")};
//			for(int l = 0; l < attr.length; l++){
//				if(attr[l]!=null){
//					int row = automatica.Utility.getRowNum(objectTable,attr[l],"reference");
//					if(row != -1){
//						int role = objectTable.getInt(row, "role");
//						if(role == 0){
//							constraintTable.set(t, "attribute"+(l+1), objectTable.getString(row, "geobject"));
//						}
//					}
//				}
//			}		
//		}
		
		for(int t = 0; t < constraintTable.getRowCount(); t++){
			if(constraintTable.getInt(t, "role")==1){
				StringBuffer str = new StringBuffer();
				str.append(constraintTable.getString(t, "vocabulary").replace(incidentCircle, "incident").replace("pointOnC", "incident")+"(");
				String[] attr = {constraintTable.getString(t, "attribute1"),constraintTable.getString(t, "attribute2"),
						constraintTable.getString(t, "attribute3")};

				for(int l = 0; l < attr.length; l++){
					if(attr[l]!=null){
						if(attr[l].indexOf("(")!=-1){
							str.append(attr[l]+",");
						}else{
						int row = automatica.Utility.getRowNum(objectTable,attr[l],"reference");
							if(row != -1){
								int role = objectTable.getInt(row, "role");
								if(role == 0){
									str.append(objectTable.getString(row, "geobject")+",");
								}else
									if(role>=1){
										str.append(attr[l]+",");
									}
							}
						}
					}
				}	
				if(str.lastIndexOf(",")!=-1){
					str.replace(str.lastIndexOf(","), str.length(), ")");
				}else{
					str.append(")");
				}
				
				constraintTable.setString(t, "geobject", str.toString());
				
			}
		}

//		for(int i = 0 ; i < constraintTable.getRowCount(); i++){
//			if(constraintTable.getInt(i, "role")==1){
//				String str = constraintTable.getString(i, "vocabulary").replace(incidentCircle, "incident")+"("+constraintTable.getString(i, "attribute1")+","+constraintTable.getString(i, "attribute2")+")";
//				constraintTable.setString(i, "geobject", str);
//				constraints.add(str);
//			}
//		}
	}
	
	//generate geobjects for objectTable
	private String getGeobject4ObjectTable(int i){
		String reference = objectTable.getString(i, "reference");
		StringBuffer geobject = new StringBuffer(1);
		String volcabulary = objectTable.getString(i, "vocabulary");
		String[] attr = {objectTable.getString(i, "attribute1"),objectTable.getString(i, "attribute2"),objectTable.getString(i, "attribute3")};
		geobject.append(volcabulary+"(");
		int attrRowNum[] = {automatica.Utility.getRowNum(objectTable,attr[0],"reference"),
				automatica.Utility.getRowNum(objectTable,attr[1],"reference"),automatica.Utility.getRowNum(objectTable,attr[2],"reference")};
		for(int t = 0; t < attrRowNum.length; t++){
			if(attrRowNum[t]!=-1){
				if(objectTable.getInt(attrRowNum[t], "role")>=1){
					//the attribute [t] must be some kind of point
					geobject.append(attr[t]+",");
				}else{
					//the attribute [t] must be not any kind of point 
					if(objectTable.getString(attrRowNum[t],"geobject")!=null){
						//when the reference exits in one of the attributes of the current object, we should remove it
						int occurenceIndex = getOccurenceIndex(objectTable,reference,attrRowNum[t]);
						if(occurenceIndex!=-1){
							//deal with the case that the attribute substituted is not the first one
							if(t>0){
								int start = geobject.indexOf("(")+1;
								int end = geobject.length();
								String s = geobject.substring(start, end);
								geobject.replace(start, end, objectTable.getString(attrRowNum[t],"attribute"+(occurenceIndex%2+1))+",").append(s);
							}else{
								geobject.append(objectTable.getString(attrRowNum[t],"attribute"+(occurenceIndex%2+1))+",");
							}
						}else{
							geobject.append(objectTable.getString(attrRowNum[t],"geobject")+",");
						}
					}else{
						String sub = getGeobject4ObjectTable(attrRowNum[t]);
						objectTable.setString(attrRowNum[t], "geobject", sub);
						int occurenceIndex = getOccurenceIndex(objectTable,reference,attrRowNum[t]);
						if(occurenceIndex!=-1){
							//deal with the case that the attribute substituted is not the first one
							if(t>0){
								int start = geobject.indexOf("(")+1;
								int end = geobject.length();
								String s = geobject.substring(start, end);
								geobject.replace(start, end, objectTable.getString(attrRowNum[t],"attribute"+(occurenceIndex%2+1))+",").append(s);
							}else{
								geobject.append(objectTable.getString(attrRowNum[t],"attribute"+(occurenceIndex%2+1))+",");
							}						
						}else{
							geobject.append(sub+",");
						}
					}
				}
					
			}
		}
		if(geobject.lastIndexOf(",")!=-1){
			geobject.replace(geobject.lastIndexOf(","), geobject.length(), ")");
		}else{
			geobject.append(")");
		}
		return geobject.toString();
		
	}
	
	//get the index of occurance of ref in the geobject at row
	private int getOccurenceIndex(Table objectTable, String ref, int row){
		int result = -1;
		if(row != -1){
			String[] attr = {objectTable.getString(row, "attribute1"),objectTable.getString(row, "attribute2")};
			for(int i = 0; i < attr.length; i++){
				if(attr[i]!=null && attr[i].indexOf(ref)!=-1){
					result = i+1;
					break;
				}
			}
		}
		
		return result;
	}
	
	void print(){
		System.out.println("role------reference------vocabulary------attribute1------attribute2------attribute3------geobject------pointCount------objectCount");
		for(int i = 0; i < objectTable.getRowCount(); i++){
			System.out.println(objectTable.getInt(i, "role")+"----"+objectTable.getString(i, "reference")+"----"
					+objectTable.getString(i, "vocabulary")+"----"+objectTable.getString(i, "attribute1")+"----"+
					objectTable.getString(i, "attribute2")+"----"+objectTable.getString(i, "attribute3")+
					"----"+objectTable.getString(i, "geobject")+"----"+
					objectTable.getInt(i, "pointCount")+"----"+objectTable.getString(i, "objectCount"));
		}	
		System.out.println("role------reference------vocabulary------attribute1------attribute2------attribute3------geobject");
		for(int i = 0; i < constraintTable.getRowCount(); i++){
			System.out.println(constraintTable.getInt(i, "role")+"----"+constraintTable.getString(i, "reference")+"----"
					+constraintTable.getString(i, "vocabulary")+"----"+constraintTable.getString(i, "attribute1")+
					"----"+constraintTable.getString(i, "attribute2")+"----"+constraintTable.getString(i, "attribute3")+
					"----"+constraintTable.getString(i, "geobject"));
		}	
	}
	
	void output(String path){
		StringBuffer result = new StringBuffer();
		for(int i = 0; i < objectTable.getRowCount(); i++){
			if(objectTable.getInt(i, "role")>-1){
				result.append(objectTable.getString(i, "reference")+":=");
				if(objectTable.getInt(i, "role")!=0){
					result.append("("+objectTable.getString(i, "attribute1")+","+objectTable.getString(i, "attribute2")+")\n");
				}else{
					result.append(objectTable.getString(i, "geobject")+"\n");
				}
			}
		}	
		for(int i = 0; i < constraintTable.getRowCount(); i++){
			if(constraintTable.getInt(i, "role")>0){
				result.append(constraintTable.getString(i, "vocabulary").replace("incidentCircle", "pointOnC")+"("+constraintTable.getString(i, "attribute1")+","+constraintTable.getString(i, "attribute2")+")\n");
			}
		}
		Utility.saveFile(new JFrame(), result.toString(), new File(path));
	}
	
	
 	private void initialCount(){
		for(int i = 0; i < objectTable.getRowCount(); i++){
			String vocabulary = objectTable.getString(i, "vocabulary");
			//set the initial object count for advanced concepts
			if(vocabulary.equals("foot")){
				objectTable.setInt(i,"objectCount",2);
				objectTable.setInt(i,"pointCount",0);
			}else
				if(vocabulary.equals("intersection")){
					objectTable.setInt(i,"objectCount",2);
					objectTable.setInt(i,"pointCount",0);
				}else
				if(vocabulary.equals("midpoint")){
					objectTable.setInt(i,"objectCount",2);
					objectTable.setInt(i,"pointCount",0);
				}else
				if(vocabulary.equals("circle")){
					objectTable.setInt(i,"objectCount",1);
					objectTable.setInt(i,"pointCount",0);
				}else{
					objectTable.setInt(i,"objectCount",0);
					objectTable.setInt(i,"pointCount",0);
				}
		}
	}
	
	void countOccurence(){
		
		//initialize the count of objects
		initialCount();
		
 		//count the object occurence times from constraint table
		for(int i = 0; i < constraintTable.getRowCount();i++){
			//suppose that the constraints are triple relations 
			if(constraintTable.getInt(i, "role")>0){
				String[] attr = {constraintTable.getString(i, "attribute1"),
						constraintTable.getString(i, "attribute2"),constraintTable.getString(i, "attribute3")};
				for(int j = 0; j < attr.length; j++){
					countObjectOccurenceFromFunction(attr[j]);	
				}
			}
		}
		
		//count the object occurence times from object table
		for(int i = 0; i < objectTable.getRowCount();i++){
			//suppose that the constraints are triple relations 
			if(objectTable.getInt(i, "role")>0){
				String[] attr = {objectTable.getString(i, "attribute1"),objectTable.getString(i, "attribute2")};
				for(int j = 0; j < attr.length; j++){
					countObjectOccurenceFromFunction(attr[j]);
				}
			}
		}
		
		//copy objectCount to pointCount
		for(int i = 0; i < objectTable.getRowCount();i++){
			if(objectTable.getInt(i, "role")>0){
				objectTable.setInt(i, "pointCount", objectTable.getInt(i, "objectCount"));	
			}
		}
		
		
		//count the total numbers of point occurence times
		for(int i = 0; i < objectTable.getRowCount();i++){
			if(objectTable.getInt(i, "role")==0){		
				int repeatedNum = objectTable.getInt(i, "objectCount");
				String obj = objectTable.getString(i, "geobject");
				countPointOccurenceFromFunction(obj,repeatedNum);
			}
//			if(objectTable.getInt(i, "role")==2){
//				if(objectTable.getString(i, "vocabulary").equals("foot")){
//					String obj = objectTable.getString(i, "geobject");
//					Vector<String> list = Utility.generateTermSet(obj);
//					for(int k = 1; k < list.size(); k++){
//						if(list.get(k).indexOf("(")!=-1){
//							countPointOccurenceFromFunction(list.get(k),2);
//						}else{
//							countPointOccurenceFromFunction(list.get(k),1);
//						}
//					}
//
//				}else
//				if(objectTable.getString(i, "vocabulary").equals("midpoint")||objectTable.getString(i, "vocabulary").equals("intersection")){
//					String obj = objectTable.getString(i, "geobject");
//					countPointOccurenceFromFunction(obj,1);
//				}
//			}
		}
		
		
		
		//In the objectTable, one label may occur in more than one rows, so we have to count them together
		Vector<Integer> doneList = new Vector<Integer>(1,1); 
		for(int i = 0; i < objectTable.getRowCount(); i++){
			boolean flag = true;
			for(int k = 0; k < doneList.size(); k++){
				if(doneList.get(k)==i){
					flag = false;
					break;
				}
			}
			if(flag){
				Vector<Integer> repeatList = new Vector<Integer>(1,1);
				int countSum = objectTable.getInt(i, "pointCount");
				repeatList.add(i);
				for(int j = i+1; j < objectTable.getRowCount(); j++){
					if(objectTable.getString(i, "reference").equals(objectTable.getString(j, "reference"))){
						repeatList.add(j);
						doneList.add(j);
						countSum = countSum + objectTable.getInt(j, "pointCount");
					}
				}
				
				for(int t = 0; t < repeatList.size(); t++){
					objectTable.setInt(repeatList.get(t), "pointCount", countSum);
				}
			}
		}

		
	}

	private void countPointOccurenceFromFunction(String obj, int repeatedNum){
		if(obj!=null){
			if(obj.indexOf("(")!=-1){
				Vector<String> v = Utility.generateTermSet(obj);
				for(int p = 1; p < v.size(); p++){
					countPointOccurenceFromFunction(v.get(p),repeatedNum);
				}
			}else{
				Vector<Integer> objectRowNum = automatica.Utility.getRowNumList(objectTable,obj,"reference");
				for(int i = 0; i < objectRowNum.size(); i++){
					objectTable.setInt(objectRowNum.get(i), "pointCount", objectTable.getInt(objectRowNum.get(i), "pointCount")+repeatedNum);
				}
			}
		}
	}
	
	private void countObjectOccurenceFromFunction(String obj){
		if(obj!=null){ 
			if(obj.indexOf("(")!=-1){
				Vector<String> v = Utility.generateTermSet(obj);
				for(int p = 1; p < v.size(); p++){
					countObjectOccurenceFromFunction(v.get(p));
				}
			}else{
				Vector<Integer> objectRowNum = automatica.Utility.getRowNumList(objectTable,obj,"reference");
				for(int i = 0; i < objectRowNum.size(); i++){
					objectTable.setInt(objectRowNum.get(i), "objectCount", objectTable.getInt(objectRowNum.get(i), "objectCount")+1);
				}
			}
		}
	}
	
	
	void reasoning(){
		//remove redundant incidences: incident(A,l) and incident(B,l)
		for(int k = 0; k < constraintTable.getRowCount(); k++){
			if(constraintTable.getInt(k, "role") > 0){
				if(constraintTable.getString(k, "vocabulary").equals("incident")){
					String objLabel = constraintTable.getString(k, "attribute2");
					int buf = automatica.Utility.getRowNum(objectTable,objLabel,"reference");
					boolean done = false;
					for(int t = 0; t < constructedLine.size(); t++){
						if(constructedLine.get(t).equals(objLabel)){
							done = true;
							break;
						}
					}
					
					if(!done){
					
						//collect all points on a line
						Vector<String> pointsOnLine = new Vector<String>(1,1);
						String vocabulary = objectTable.getString(buf, "vocabulary");
						constructedLine.add(objLabel);
						
						//initial the pointsOnLine
						pointsOnLine.add(constraintTable.getString(k, "attribute1"));
						if(vocabulary.equals("segment")){
							String label3 = objectTable.getString(buf, "attribute1");
							String label4 = objectTable.getString(buf, "attribute2");

									//pointsOnLine.add(label3);

									//pointsOnLine.add(label4);
			
						}else				
							if(vocabulary.equals("halfline")){
								String label4 = objectTable.getString(buf, "attribute2");

										pointsOnLine.add(label4);

							}
						
						for(int j = k+1; j < constraintTable.getRowCount(); j++){
							if(objLabel.equals(constraintTable.getString(j, "attribute2"))&&constraintTable.getInt(j, "role")>0
									&&constraintTable.getString(j, "vocabulary").equals("incident")){
								String label = constraintTable.getString(j, "attribute1");

										pointsOnLine.add(label);

							}
						}
						
						for(int i = 0; i < pointsOnLine.size(); i++){
							String var = pointsOnLine.get(i);
							for(int j = i+1; j < pointsOnLine.size(); j++){
								if(pointsOnLine.get(j)!=null && pointsOnLine.get(j).equals(var)){
									pointsOnLine.set(j, null);
								}
							}
						}
						
						//initial the counts
						
						Vector<Integer> counts = new Vector<Integer>(1,1);
						//Vector<Integer> rows = new Vector<Integer>(1,1);
						for(int t = 0; t < pointsOnLine.size(); t++){
							if(pointsOnLine.get(t)!=null){
								int row = automatica.Utility.getRowNum(objectTable,pointsOnLine.get(t),"reference");
								//rows.add(row);
								int count = objectTable.getInt(row, "pointCount");
								counts.add(count);
							}else{
								counts.add(-10);
							}
						}
						
						
						//select the two points with most weights
						
						int index1 = 0;
						int index2 = -1;
						for(int t = 0; t < pointsOnLine.size(); t++){
							if(counts.get(t) > counts.get(index1)){
								index1 = t;
							}
						}
						for(int p = 0; p < pointsOnLine.size(); p++){
							if(p!=index1){
								if(counts.get(p)<=counts.get(index1)){
									if(index2 == -1){
										index2 = p;
									}else
										if(counts.get(p)>counts.get(index2)){
											index2 = p;
										}
								}
							}
						}
						
						String var1 = pointsOnLine.get(index1);
						String var2 = "";
						if(index2!=-1){
							var2 = pointsOnLine.get(index2);
						}
						if(vocabulary.equals("line")){
							if(pointsOnLine.size()==1){
								String attr = objectTable.getString(buf, "attribute2");
								objectTable.setString(buf, "attribute2", var1);
								for(int q = 0; q < constraintTable.getRowCount(); q++){
									String attr1 = constraintTable.getString(q, "attribute1");
									String attr2 = constraintTable.getString(q, "attribute2");
									constraintTable.setString(q, "attribute1", attr1.replace("("+attr, "("+var1).replace(","+attr, ","+var1));
									constraintTable.setString(q, "attribute2", attr2.replace("("+attr, "("+var1).replace(","+attr, ","+var1));
								}
							}else{
								String attr = objectTable.getString(buf, "attribute1");
								String attr0 = objectTable.getString(buf, "attribute2");
								objectTable.setString(buf, "attribute1", var1);
								objectTable.setString(buf, "attribute2", var2);
								for(int q = 0; q < constraintTable.getRowCount(); q++){
									String attr1 = constraintTable.getString(q, "attribute1");
									String attr2 = constraintTable.getString(q, "attribute2");
									constraintTable.setString(q, "attribute1", attr1.replace("("+attr, "("+var1).replace(","+attr, ","+var1)
											.replace("("+attr0, "("+var2).replace(","+attr0, ","+var2));
									constraintTable.setString(q, "attribute2", attr2.replace("("+attr, "("+var1).replace(","+attr, ","+var1)
											.replace("("+attr0, "("+var2).replace(","+attr0, ","+var2));
								}
							}
						}else
							if(vocabulary.equals("halfline")){
								String attr = objectTable.getString(buf, "attribute2");
								objectTable.setString(buf, "attribute2", var1);
								for(int q = 0; q < constraintTable.getRowCount(); q++){
									String attr1 = constraintTable.getString(q, "attribute1");
									String attr2 = constraintTable.getString(q, "attribute2");
									constraintTable.setString(q, "attribute1", attr1.replace("("+attr, "("+var1).replace(","+attr, ","+var1));
									constraintTable.setString(q, "attribute2", attr2.replace("("+attr, "("+var1).replace(","+attr, ","+var1));
								}
							}else
								if(vocabulary.equals("segment")){
									//objectTable.setString(buf, "attribute1", var1);
									//objectTable.setString(buf, "attribute2", var2);
								}
						this.updateGeobject4ObjectTable();
						countOccurence();
					
					}
					

					
					//if a point is incident to a line, then the represented points should be replaced
//					if(vocabulary.equals("line")){
//						for(int j = k+1; j < constraintTable.getRowCount(); j++){
//							if(objLabel.equals(constraintTable.getString(j, "attribute2"))&&constraintTable.getInt(j, "role")>0
//									&&constraintTable.getString(j, "vocabulary").equals("incident")){
//								String label1 = constraintTable.getString(k, "attribute1");
//								String label2 = constraintTable.getString(j, "attribute1");
//								objectTable.setString(buf, "attribute1", label1);
//								objectTable.setString(buf, "attribute2", label2);
//								this.updateGeobject4ObjectTable();
//								//countOccurence();
//								break;
//
//							}
//						}
//
//					}
//					for(int j = k+1; j < constraintTable.getRowCount(); j++){
//						String newStr = null;
//						
//						if(objLabel.equals(constraintTable.getString(j, "attribute2"))&&constraintTable.getInt(j, "role")>0
//								&&constraintTable.getString(j, "vocabulary").equals("incident")){
//							String label1 = constraintTable.getString(k, "attribute1");
//							String label2 = constraintTable.getString(j, "attribute1");
//							int row1 = automatica.Utility.getRowNum(objectTable,label1,"reference");
//							int row2 = automatica.Utility.getRowNum(objectTable,label2,"reference");		
//							String label3 = objectTable.getString(buf, "attribute1");
//							String label4 = objectTable.getString(buf, "attribute2");
//							int row3 = automatica.Utility.getRowNum(objectTable,label3,"reference");
//							int row4 = automatica.Utility.getRowNum(objectTable,label4,"reference");
//	
//							int count1 = objectTable.getInt(row1, "pointCount");
//							int count2 = objectTable.getInt(row2, "pointCount");
//							int count3 = objectTable.getInt(row3, "pointCount");
//							int count4 = objectTable.getInt(row4, "pointCount");
//							
//							//determine which label should be eliminated
//							if(count3<=count4){
//								if((count3 < count1 || count3 < count2)){
//									if(count1 <= count2){
//										int flag = 0;
//										//check whether it will be incident(A,line(A,B))
//										if(!label3.equals(label2) && !label4.equals(label2)){
//											objectTable.setString(buf, "attribute1", label2);
//											newStr = objectTable.getString(buf, "geobject").replace("("+label3+",", "("+label2+",");
//											objectTable.setString(buf, "geobject", newStr);
//											constraintTable.setInt(j, "role", 0);
//											flag++;
//											//reset the occurence times
//											//countOccurence();
//										}
//										
//										if(count4 <= count1){
//											if(!label3.equals(label1) && !label4.equals(label1)){
//												objectTable.setString(buf, "attribute2", label1);
//												newStr = objectTable.getString(buf, "geobject").replace(","+label4+")", ","+label1+")");
//												objectTable.setString(buf, "geobject", newStr);
//												constraintTable.setInt(k, "role", 0);
//												flag++;
//												countOccurence();
//											}
//										}
//										//if two attributes are replaced, then break
//										if(flag == 2){
//											break;
//										}
//
//									}else{
//										int flag = 0;
//										if(!label3.equals(label1) && !label4.equals(label1)){
//											objectTable.setString(buf, "attribute1", label1);
//											newStr = objectTable.getString(buf, "geobject").replace("("+label3+",", "("+label1+",");
//											objectTable.setString(buf, "geobject", newStr);
//											constraintTable.setInt(k, "role", 0);
//											flag++;
//											//reset the occurence times
//											countOccurence();
//										}
//										
//										if(count4 <= count2){
//											if(!label3.equals(label2) && !label4.equals(label2)){
//												objectTable.setString(buf, "attribute2", label2);
//												newStr = objectTable.getString(buf, "geobject").replace(","+label4+")", ","+label2+")");
//												objectTable.setString(buf, "geobject", newStr);
//												constraintTable.setInt(j, "role", 0);
//												flag++;
//												//reset the occurence times
//												countOccurence();
//											}
//										}
//										
//										//if two attributes are replaced, then break
//										if(flag == 2){
//											break;
//										}
//									}
//								}
//							}else{
//								if((count4 < count1 || count4 < count2)){
//									if(count1 <= count2){
//										int flag = 0;
//										if(!label3.equals(label2) && !label4.equals(label2)){
//											objectTable.setString(buf, "attribute2", label2);
//											newStr = objectTable.getString(buf, "geobject").replace(","+label4+")", ","+label2+")");
//											objectTable.setString(buf, "geobject", newStr);
//											constraintTable.setInt(j, "role", 0);
//											flag++;
//											//reset the occurence times
//											countOccurence();
//										}
//										
//										if(count3 <= count1){
//											if(!label3.equals(label1) && !label4.equals(label1)){
//												objectTable.setString(buf, "attribute1", label1);
//												newStr = objectTable.getString(buf, "geobject").replace("("+label3+",", "("+label1+",");
//												objectTable.setString(buf, "geobject", newStr);
//												constraintTable.setInt(k, "role", 0);
//												flag++;
//												//reset the occurence times
//												countOccurence();
//											}
//										}
//										
//										//if two attributes are replaced, then break
//										if(flag == 2){
//											break;
//										}
//
//									}else{
//										int flag = 0;
//										if(!label3.equals(label1) && !label4.equals(label1)){
//											objectTable.setString(buf, "attribute2", label1);
//											newStr = objectTable.getString(buf, "geobject").replace(","+label4+")", ","+label1+")");
//											objectTable.setString(buf, "geobject", newStr);
//											constraintTable.setInt(k, "role", 0);
//											flag++;
//											//reset the occurence times
//											countOccurence();
//										}
//										
//										if(count3 <= count2){
//											if(!label3.equals(label2) && !label4.equals(label2)){
//												objectTable.setString(buf, "attribute1", label2);
//												newStr = objectTable.getString(buf, "geobject").replace("("+label3+",", "("+label2+",");
//												objectTable.setString(buf, "geobject", newStr);
//												constraintTable.setInt(j, "role", 0);
//												flag++;
//												//reset the occurence times
//												countOccurence();
//											}
//										}
//										//if two attributes are replaced, then break
//										if(flag == 2){
//											break;
//										}
//									}
//								}
//							}
//						}
//					}
				}else
					if(constraintTable.getString(k, "vocabulary").equals("pointOnC")){
						String objLabel = constraintTable.getString(k, "attribute2");
						Vector<String> labels = new Vector<String>(1,1);
						Vector<Integer> objectRows = new Vector<Integer>(1,1);
						labels.add(constraintTable.getString(k, "attribute1"));
						objectRows.add(k);
						for(int j = k+1; j < constraintTable.getRowCount(); j++){
							if(objLabel.equals(constraintTable.getString(j, "attribute2"))&&constraintTable.getInt(j,"role")>0){
								labels.add(constraintTable.getString(j, "attribute1"));
								objectRows.add(j);
								System.out.println("Label: " + constraintTable.getString(j, "attribute1"));
							}
						}
						System.out.println("Labelsize: " + labels.size());
						
						if(labels.size()==1){
							//the circle is redundant
							constraintTable.setInt(k, "role", 0);
						}else
							if(labels.size()==2){
								int row1 = automatica.Utility.getRowNum(objectTable,labels.get(0),"reference");
								int row2 = automatica.Utility.getRowNum(objectTable,labels.get(1),"reference");
								int objRow = automatica.Utility.getRowNum(objectTable,objLabel,"geobject");
								int count1 = objectTable.getInt(row1, "pointCount");
								int count2 = objectTable.getInt(row2, "pointCount");
								if(count1 <= count2){
									String length = objectTable.getString(objRow, "attribute2");
									String newObj = objectTable.getString(objRow, "geobject").replace(length, labels.get(1));
									objectTable.setString(objRow, "attribute2", labels.get(1));
									objectTable.setString(objRow, "geobject", newObj);
									constraintTable.setInt(row2, "role", 0);
								}else{
									String length = objectTable.getString(objRow, "attribute2");
									String newObj = objectTable.getString(objRow, "geobject").replace(length, labels.get(0));
									objectTable.setString(objRow, "attribute2", labels.get(0));
									objectTable.setString(objRow, "geobject", newObj);
									constraintTable.setInt(row1, "role", 0);
								}
							}else
								if(labels.size()>=3){
									//select the first three labels with most counts
									Vector<Integer> labelCounts = new Vector<Integer>(1,1);
									for(int m = 0; m < labels.size(); m++){
										labelCounts.add(objectTable.getInt(automatica.Utility.getRowNum(objectTable,labels.get(m),"reference"), "pointCount"));
										System.out.println("Counts:" + labelCounts.get(m));
									}
									int[] a = new int[3];
									a[0] = 0;
									for(int p = 1; p < labelCounts.size(); p++){
										if(labelCounts.get(p) > labelCounts.get(a[0])){
											a[0] = p;
										}
									}
									labelCounts.set(a[0], 0);
									a[1] = 0;
									for(int p = 1; p < labelCounts.size(); p++){
										if(labelCounts.get(p) > labelCounts.get(a[1])){
											a[1] = p;
										}
									}
									labelCounts.set(a[1],0);
									a[2] = 0;
									for(int p = 1; p < labelCounts.size(); p++){
										if(labelCounts.get(p) > labelCounts.get(a[2])){
											a[2] = p;
										}
									}
									
									//replace the circle object
									int objRow = automatica.Utility.getRowNum(objectTable,objLabel,"reference");
									objectTable.setString(objRow, "geobject", "circle("+labels.get(a[0])+","+labels.get(a[1])+","+labels.get(a[2])+")");
									String center = objectTable.getString(objRow, "attribute1");
									for(int m = 1; m < 4; m++){
										objectTable.setString(objRow, "attribute"+m, labels.get(a[m-1]));
									}
									
									
									//set the role with 0
									constraintTable.setInt(objectRows.get(a[0]), "role", 0);
									constraintTable.setInt(objectRows.get(a[1]), "role", 0);
									constraintTable.setInt(objectRows.get(a[2]), "role", 0);
									
									for(int t = 0; t < objectRows.size(); t++){
										if(t!=a[0]&&t!=a[1]&&t!=a[2]){
											constraintTable.setString(objectRows.get(t), "vocabulary", incidentCircle);
										}
									}
									
									
									//check whether the center should be recovered
									boolean r = false;
									for(int p = 0; p < constraintTable.getRowCount(); p++){
										if(constraintTable.getString(p, "vocabulary").equals("incident")){											
											if(constraintTable.getString(p, "attribute1").equals(center)){
												r = true;
												break;
											}else{
												int index = automatica.Utility.getRowNum(objectTable, constraintTable.getString(p, "attribute2"), "reference");
												String obj = objectTable.getString(index, "geobject");
												if(obj.indexOf(center)!=-1){
													r= true;
													break;
												}
											}
												
										}
									}
									//recover the information of center of the circle
									
									if(r){									
										constraintTable.addRow();
										int current = constraintTable.getRowCount()-1;
										constraintTable.set(current, "role", 1);
										constraintTable.set(current, "vocabulary", "equal");
										constraintTable.set(current, "attribute1", "distance("+center+","+labels.get(a[0])+")");
										constraintTable.set(current, "attribute2", "distance("+center+","+labels.get(a[1])+")");
										
										constraintTable.addRow();
										int current1 = constraintTable.getRowCount()-1;
										constraintTable.set(current1, "role", 1);
										constraintTable.set(current1, "vocabulary", "equal");
										constraintTable.set(current1, "attribute1", "distance("+center+","+labels.get(a[0])+")");
										constraintTable.set(current1, "attribute2", "distance("+center+","+labels.get(a[2])+")");
									}
								}
						countOccurence();
					}
			}
		}
		
		
		//check whether incident(A,line(A,B))
		for(int i = 0; i < constraintTable.getRowCount();i++){
			//suppose that the constraints are binary relations
			String attr1 = constraintTable.getString(i, "attribute1");
			String attr2 = constraintTable.getString(i, "attribute2");
			int attr1RowNum = automatica.Utility.getRowNum(objectTable,attr1,"reference");
			int attr2RowNum = automatica.Utility.getRowNum(objectTable,attr2,"reference");
			
			//deal with relation of incident
			if(constraintTable.getString(i, "vocabulary").equals("incident")){
				if(attr2RowNum!=-1){
					//check whether it is the case incident(A,line(A,B))
					if(attr1.equals(objectTable.getString(attr2RowNum, "attribute1"))||attr1.equals(objectTable.getString(attr2RowNum, "attribute2"))){
						constraintTable.setInt(i, "role", 0);
					}
				}
			}
		}
		
		//remove redundant equal distances
		
		countOccurence();
	}
	
void removeRedundantObjects(){
		
		//if the count number of a point is less than threshold, then the point is useless; otherwise, the point is useful. 
		for(int i = 0; i < objectTable.getRowCount(); i++){
			if(objectTable.getInt(i, "role")>=1 && objectTable.getInt(i, "pointCount") < threshold){
				//the point is redundant
				objectTable.setInt(i, "role", -1);
				String redundantReference = objectTable.getString(i, "reference");
				for(int j = 0 ; j < constraintTable.getRowCount(); j++){					
					String[] attr = {constraintTable.getString(j, "attribute1"),constraintTable.getString(j, "attribute2"),
							constraintTable.getString(j, "attribute3")};
					for(int k = 0; k < attr.length; k++){
						if(attr[k]!=null){
							if(constraintTable.getInt(j, "role")>0 && attr[k].equals(redundantReference)){
								constraintTable.setInt(j,"role",-1);
							}else{
								String vocabulary = constraintTable.getString(j, "vocabulary");
								int row = automatica.Utility.getRowNum(objectTable, attr[k], "reference");
								int occurenceIndex = this.getOccurenceIndex(objectTable, redundantReference, row);
								if(occurenceIndex!=-1){
									if(vocabulary.equals("incident")&&occurenceIndex!=-1){
										String buf = constraintTable.getString(j, "attribute1");
										objectTable.setString(row, "attribute"+occurenceIndex, buf);
									}
									constraintTable.setInt(j,"role",-1);	
								}else{
									if(attr[k].indexOf(redundantReference+",")!=-1||attr[k].indexOf(","+redundantReference)!=-1){
										constraintTable.setInt(j,"role",-1);	
									}
								}
							}
						}
					}
				}
			}
		}
		//update the geobject for objectTable
		updateGeobject4ObjectTable();
		

		
		updateGeobject4ConstraintTable();
		
		//countOccurence();

	}
	

	public Table getObjectTable() {
		return objectTable;
	}

	public void setObjectTable(Table objectTable) {
		this.objectTable = objectTable;
	}

	public Table getConstraintTable() {
		return constraintTable;
	}

	public void setConstraintTable(Table constraintTable) {
		this.constraintTable = constraintTable;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}


	private Table objectTable;
	private Table constraintTable;
	private String name = "Proposition";
	private String incidentCircle = "incidentCircle";
	private int threshold = 3;
	Vector<String> constructedLine = new Vector<String>(1,1);

}
